//
// Created by feng on 19-3-28.
//
#include "RandomGenerator.cuh"

using namespace solar::cuda;
std::default_random_engine RandomGenerator::generator;

void RandomGenerator::initSeed()
{
    auto mrand = (unsigned int)time(NULL);
    srand(mrand);
    generator.seed(mrand);
}

void RandomGenerator::initSeed(unsigned int seed)
{
    srand(seed);
    generator.seed(seed);
}

auto RandomGenerator::cpuUniform(float* h_0_1_array, int array_length) -> bool
{
    if (h_0_1_array == nullptr)
    {
        return false;
    }

    for (int i = 0; i < array_length; ++i)
    {
        h_0_1_array[i] = (float)((float)rand() / RAND_MAX);
    }
    return true;
}

auto RandomGenerator::gpuUniform(float* d_0_1_array, int array_length) -> bool
{
    if (d_0_1_array == nullptr)
    {
        return false;
    }
    // Generate 0-1 array
    curandGenerateUniform(gen, d_0_1_array, array_length);
    return true;
}

auto RandomGenerator::cpuGaussian(float* h_0_1_array, float mean, float stddev, int array_length) -> bool
{
    if (h_0_1_array == nullptr)
    {
        return false;
    }
    std::normal_distribution<float> distribution(mean, stddev);

    for (int i = 0; i < array_length; ++i)
    {
        h_0_1_array[i] = distribution(generator);
    }
    return true;
}

auto RandomGenerator::gpuGaussian(float* d_0_1_array, float mean, float stddev, int array_length) -> bool
{
    if (d_0_1_array == nullptr)
    {
        return false;
    }
    // printf("===== enter func: gpuGaussian()\n");
    // printf("mean = %f, stddev = %f, array_length = %d\n", mean, stddev, array_length);
    curandGenerateNormal(gen, d_0_1_array, array_length, mean,
                         stddev); // 这句代码貌似不起作用。。。

    // float *c_array;
    // c_array = (float*)malloc(sizeof(float)*array_length);
    // cudaMemcpy(c_array, d_0_1_array, sizeof(float)*array_length, cudaMemcpyDeviceToHost);
    // printf("================printf d_0_1_array data in cuda begins\n");
    // for(int i=0 ; i<array_length ; i++)
    // {
    //     printf("gaussian[%d]: %f \n", i, c_array[i]);
    // }
    // printf("================printf d_0_1_array data in cuda ends\n");

    return true;
}

auto RandomGenerator::cpuUniform(int* h_min_max_array, int low_threshold, int high_threshold,
                                 int array_length) -> bool
{
    if (h_min_max_array == nullptr)
    {
        return false;
    }

    int range = high_threshold - low_threshold;
    for (int i = 0; i < array_length; ++i)
    {
        h_min_max_array[i] = int(float(rand()) / float(RAND_MAX) * range + low_threshold);
    }
    return true;
}
